import { Key, TreeCache, TreeNode } from './interface'
import { keys } from './utils'
import { filterTree } from './serach'

/**
 * 数据模型
 */
export class VoidTree<Raw extends Record<string, any>> {
  /**
   * 原始数据
   * @private
   */
  private readonly _treeNodes: TreeNode<Raw>[]

  /**
   * 处理后对外展示的数据
   */
  treeNodes: TreeNode<Raw>[]
  /**
   * 自定义的一些缓存
   */
  cache: TreeCache<Raw>
  /**
   * 选择的key值
   */
  checkKeys: Key[]

  constructor(treeNodes: TreeNode<Raw>[], cache: TreeCache<Raw>) {
    this._treeNodes = treeNodes
    this.treeNodes = treeNodes
    this.cache = cache
    this.checkKeys = []
  }

  /**
   * 获取某项缓存
   * @param key
   */
  getCache(key: string) {
    return this.cache[key]
  }

  /**
   * 获取key-node 结构的Map数据
   */
  get treeNodeMap() {
    return this.cache.key
  }

  /**
   * 通过key获取单个节点信息
   * @param key
   */
  getNode(key: Key) {
    return this.treeNodeMap.get(key)
  }

  /**
   * 通过多个key获取多个节点信息
   * @param key
   * @param ignoreEmpty
   */
  getNodes(key: Key | Key[], ignoreEmpty = true) {
    const nodes: TreeNode<Raw>[] = []
    const keyList = keys(key)
    keyList.forEach((key) => {
      const node = this.getNode(key) as any
      if (!node && ignoreEmpty) {
        return
      }
      nodes.push(node)
    })
    return nodes
  }

  /**
   * 获取子节点
   * @param key
   */
  getChild(key: Key) {
    const node = this.getNode(key)
    return node?.children
  }
  /**
   * 获取父节点
   * @param key
   */
  getParent(key: Key) {
    const node = this.getNode(key)
    return node?.parent
  }

  /**
   * 选择
   * @param key
   */
  check(key: Key | Key[]) {
    const keyList = keys(key)
    keyList.forEach((item) => {
      const index = this.checkKeys.findIndex((k) => k === item)
      if (index !== -1) {
        return
      }
      this.checkKeys.push(item)
    })
  }
  /**
   * 选择
   * @param key
   */
  uncheck(key: Key | Key[]) {
    const keyList = keys(key)
    keyList.forEach((item) => {
      const index = this.checkKeys.findIndex((k) => k === item)
      if (index === -1) {
        return
      }
      this.checkKeys.splice(index, 1)
    })
  }

  /**
   * 选择
   * @param key
   */
  updateCheckKeys(key: Key | Key[]) {
    this.checkKeys = keys(key)
  }

  /**
   * 自定义选择
   * @param fn
   */
  customUpdateCheckKeys(fn: (self: VoidTree<Raw>) => Key | Key[]) {
    const _key = fn(this)
    this.updateCheckKeys(_key)
  }

  /**
   * 搜索
   * 解决一些组件库tree搜索不会筛选数据，而是加下划线
   * 方法改写自naiveui
   * @param keyword
   * @param filter
   */
  search(keyword: string, filter?: (pattern: string, v: string) => boolean) {
    if (!keyword) {
      this.treeNodes = this._treeNodes
      return
    }
    this.treeNodes = filterTree<Raw>(this._treeNodes, filter, keyword)
  }
}
